// 数组列表
class ArrayList {

    constructor(initCapacity) {
        // 当前数组大小
        let nextElePointer = 0;
        Object.defineProperty(this, 'size', {
            get() {
                return nextElePointer;
            },
            set() {
                throw new Error('无法修改size属性')
            },
            configurable: false,
        })
        // 数组的最大容量
        if (initCapacity < 1) {
            throw new Error('最小容量为1')
        }
        let _capacity = initCapacity;
        Object.defineProperty(this, 'capacity', {
            get() {
                return _capacity;
            },
            configurable: false,
        })
        // 初始化数组
        let _store = new Array(this.capacity);
        Object.defineProperty(this, 'store', {
            get() {
                console.log("有人访问了store属性")
                // 不直接返回 store ，返回store的复制对象，这样外部就无法修改到 store属性
                let newStore = new Array(this.size);
                for (let i = 0; i < this.size; i++) {
                    newStore[i] = _store[i];
                }
                return newStore;
            },
            configurable: false,
        })

        /**
         * 添加元素
         * @param ele 被添加元素
         */
        this.add = function (ele) {
            // 扩容
            this.expand()
            // 设置元素
            _store[nextElePointer] = ele;
            // 下一个元素的索引 +1
            nextElePointer++;

        }
        /**
         * 在index索引上添加 ele
         * @param index 索引
         * @param ele 被添加元素
         */
        this.addByIndex = function (index, ele) {
            // 判断是否超出数组当前的索引
            if (this.outRange(index)) {
                throw Error("超出数组范围")
            }
            // 扩容
            this.expand()
            // 数据往后挪
            for (var i = this.size - 1; i >= index; i--) {
                _store[i + 1] = _store[i];
            }
            // 设置元素
            _store[index] = ele;
            // 下一个元素的索引 +1
            nextElePointer++;
        }
        /**
         * 删除索引i上的元素
         * @param i 索引i
         */
        this.remove = function (index) {
            // 判断是否超出数组当前的索引
            if (this.outRange(index)) {
                throw Error("超出数组范围")
            }
            // 数据往前移动
            for (var i = index + 1; i < this.size; i++) {
                _store[i - 1] = _store[i];
            }
            // 下一个元素的索引 - 1
            nextElePointer--;
        }
        /**
         * 删除指定元素
         * @param ele 需要被删除的元素
         */
        this.removeEle = function (ele) {
            var findIndex = this.findIndexByEle(ele);
            if (findIndex >= 0) {
                // 数据往前移动
                for (var i = findIndex; i < nextElePointer; i++) {
                    _store[i] = _store[i + 1];
                }
                // 下一个元素的索引 - 1
                nextElePointer--;
                return true;
            }
            return false;
        }
        // 扩容的倍率
        Object.defineProperty(this, 'extendRatio', {
            get() {
                return 2;
            },
            configurable: false,
        })
        /**
         * 扩容
         */
        this.expand = function () {
            // 判断是否需求扩容
            if (!this.needExpand()) {
                return
            }
            _capacity = this.size * this.extendRatio;
            let newStore = new Array(_capacity);
            // 复制元素
            for (var index = 0; index < this.size; index++) {
                newStore[index] = _store[index];
            }
            _store = newStore;
        }

        /**
         * 把索引i上的元素替换成ele
         * @param i 索引i
         * @param ele 被替换元素
         */
        this.updateByIndex = function (i, ele) {
            if (this.outRange(i)) {
                throw Error("超出数组范围")
            }
            _store[i] = ele;
        }

        /**
         * 获取 索引 i 上的元素
         * @param i 索引i
         * @returns {*}
         */
        this.getEleByIndex = function (i) {
            if (this.isRange(i)) {
                return _store[i];
            }
            throw Error("超出数组范围")
        }

        /**
         * 找到指定元素的索引值
         * @param ele 被找元素
         * @returns {number} 指定元素的索引值
         */
        this.findIndexByEle = function (ele) {
            for (let i = 0; i < this.size; i++) {
                if (_store[i] == ele) {
                    return i;
                }
            }
            return -1;
        }
    }

    /**
     * 判断是否需要扩容
     * @returns {boolean}
     */
    needExpand() {
        if (this.size >= this.capacity) {
            return true;
        }
        return false;
    }

    /**
     * 获取当前数组的元素个数
     * @returns {int} 当前数组的元素个数
     */
    length() {
        return this.size;
    }

    /**
     * 判断i是否在范围内
     * @param i 索引
     * @returns {boolean}
     */
    isRange(i) {
        if (i < 0 || i >= this.size) {
            return false;
        }
        return true;
    }

    /**
     * 判断i是否超出范围
     * @param i
     * @returns {boolean}
     */
    outRange(i) {
        if (this.isRange(i)) {
            return false;
        }
        return true;
    }

    toArray() {
        return this.store;
    }
}

class FixedArray {
    constructor(initCapacity) {
        // 当前数组大小
        let nextElePointer = 0;
        Object.defineProperty(this, 'size', {
            get() {
                return nextElePointer;
            },
            set() {
                throw new Error('无法修改size属性')
            },
            configurable: false,
        })
        // 数组的最大容量
        if (initCapacity < 1) {
            throw new Error('最小容量为1')
        }
        let _capacity = initCapacity;
        Object.defineProperty(this, 'capacity', {
            get() {
                return _capacity;
            },
            configurable: false,
        })
        // 初始化数组
        let _store = new Array(this.capacity);
        Object.defineProperty(this, 'store', {
            get() {
                console.log("有人访问了store属性")
                // 不直接返回 store ，返回store的复制对象，这样外部就无法修改到 store属性
                let newStore = new Array(this.size);
                for (let i = 0; i < this.size; i++) {
                    newStore[i] = _store[i];
                }
                return newStore;
            },
            configurable: false,
        })

        /**
         * 添加元素
         * @param ele 被添加元素
         */
        this.add = function (ele) {
            this.checkOutRange();
            // 设置元素
            _store[nextElePointer] = ele;
            // 下一个元素的索引 +1
            nextElePointer++;
        }
        /**
         * 在index索引上添加 ele
         * @param index 索引
         * @param ele 被添加元素
         */
        this.addByIndex = function (index, ele) {
            this.checkOutRange();
            // 判断是否超出数组当前的索引
            if (this.outRange(index)) {
                throw Error("超出数组范围")
            }
            // 数据往后挪
            for (var i = this.size - 1; i >= index; i--) {
                _store[i + 1] = _store[i];
            }
            // 设置元素
            _store[index] = ele;
            // 下一个元素的索引 +1
            nextElePointer++;
        }
        /**
         * 删除索引i上的元素
         * @param i 索引i
         */
        this.remove = function (index) {
            // 判断是否超出数组当前的索引
            if (this.outRange(index)) {
                throw Error("超出数组范围")
            }
            // 数据往前移动
            for (var i = index + 1; i < this.size; i++) {
                _store[i - 1] = _store[i];
            }
            // 下一个元素的索引 - 1
            nextElePointer--;
        }
        /**
         * 删除指定元素
         * @param ele 需要被删除的元素
         */
        this.removeEle = function (ele) {
            var findIndex = this.findIndexByEle(ele);
            if (findIndex >= 0) {
                // 数据往前移动
                for (var i = findIndex; i < nextElePointer; i++) {
                    _store[i] = _store[i + 1];
                }
                // 下一个元素的索引 - 1
                nextElePointer--;
                return true;
            }
            return false;
        }

        /**
         * 把索引i上的元素替换成ele
         * @param i 索引i
         * @param ele 被替换元素
         */
        this.updateByIndex = function (i, ele) {
            if (this.outRange(i)) {
                throw Error("超出数组范围")
            }
            _store[i] = ele;
        }

        /**
         * 获取 索引 i 上的元素
         * @param i 索引i
         * @returns {*}
         */
        this.getEleByIndex = function (i) {
            if (this.isRange(i)) {
                return _store[i];
            }

            throw Error("超出数组范围")
        }

        /**
         * 找到指定元素的索引值
         * @param ele 被找元素
         * @returns {number} 指定元素的索引值
         */
        this.findIndexByEle = function (ele) {
            for (let i = 0; i < this.size; i++) {
                if (_store[i] == ele) {
                    return i;
                }
            }
            return -1;
        }
    }

    /**
     * 获取当前数组的元素个数
     * @returns {int} 当前数组的元素个数
     */
    length() {
        return this.size;
    }

    /**
     * 判断i是否在范围内
     * @param i 索引
     * @returns {boolean}
     */
    isRange(i) {
        if (i < 0 || i >= this.size) {
            return false;
        }
        return true;
    }

    /**
     * 判断i是否超出范围
     * @param i
     * @returns {boolean}
     */
    outRange(i) {
        if (this.isRange(i)) {
            return false;
        }
        return true;
    }

    checkOutRange() {
        if (this.size >= this.capacity) {
            throw Error('超出数组的范围');
        }
    }

    toArray() {
        return this.store;
    }
}


